﻿using Dapper;
using log4net;
using log4net.Core;
using MySql.Data.MySqlClient;
using NiceLabel.SDK;
using PrintDemo.BLL;
using PrintDemo.DAL;
using PrintDemo.DBUtil;
using PrintDemo.Entity;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using static Dapper.SqlMapper;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
using MySqlHelper = PrintDemo.DBUtil.MySqlHelper;

namespace PrintDemo.PrintHelp
{
    public class PrintHelper
    {
        ILog _log = LogManager.GetLogger("PrintHelp");

        StackInBLL stackInBLL = new StackInBLL();
        ProductBLL productBLL = new ProductBLL();
        StackLogBLL stackLogBLL = new StackLogBLL();
        ChangefulBLL changefulBLL = new ChangefulBLL();

        private IPrintEngine printEngine;
        private ILabel label;
        private IVariable selectedVariable;
        private string variableFormat;
        private string variableValue;
        private string variableName;
        private string variableDescription;
        private string variableLength;
        private string variableIsUsed;
        private string variableSerialization;
        private string labelFileName;
        public event PropertyChangedEventHandler PropertyChanged;
        public virtual string ViewModelName { get; protected set; }
        public string Quantity
        {
            get;
            set;
        }
        public IList<IPrintRequest> PrintRequests { get; private set; }

        protected virtual void NotifyPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        public IPrintEngine PrintEngine
        {
            get
            {
                if (this.printEngine == null)
                {
                    string sdkFilesPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "..\\..\\..\\SDKFiles");
                    /*string sdkFilesPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "bin.net");*/  //..\\..\\..\\SDKFiles
                    if (Directory.Exists(sdkFilesPath))
                    {
                        //PrintEngineFactory.SDKFilesPath = sdkFilesPath;
                    }

                    //PrintEngineFactory.PrintEngine.Initialize();
                    this.printEngine = NiceLabel.SDK.PrintEngineFactory.PrintEngine;
                    var ss = "";
                }

                return this.printEngine;
            }
        }
        public ISessionPrintRequest SessionPrintRequest
        {
            get
            {
                return this.sessionPrintRequest;
            }

            set
            {
                this.sessionPrintRequest = value;
                //this.NotifyPropertyChanged("SessionPrintRequest");
            }
        }
        private ISessionPrintRequest sessionPrintRequest;
        public ILabel Label
        {
            get
            {
                return this.label;
            }

            set
            {
                if (this.label != value)
                {
                    this.label = value;
                    this.label.PrintSettings.MonitorSpoolJobStatus = true;
                    this.SelectedVariable = null;

                    this.NotifyPropertyChanged("LabelSize");
                    this.NotifyPropertyChanged("OriginalPrinter");
                    this.NotifyPropertyChanged("PaperSize");
                    this.NotifyPropertyChanged("LabelOffset");
                    this.NotifyPropertyChanged("LabelsAcross");
                    this.NotifyPropertyChanged("Gap");
                    this.NotifyPropertyChanged("Variables");
                    this.NotifyPropertyChanged("Preview");
                    this.NotifyPropertyChanged("LabelFileName");
                }
            }
        }

        public IVariable SelectedVariable
        {
            get
            {
                return this.selectedVariable;
            }

            set
            {
                if (this.selectedVariable != value)
                {
                    this.selectedVariable = value;

                    this.UpdateVariableValues();

                    this.NotifyPropertyChanged("SelectedVariable");
                }
            }
        }
        #region Internal Methods

        /// <summary>
        /// Updates the variable values.
        /// </summary>
        internal void UpdateVariableValues()
        {
            if (this.selectedVariable != null)
            {
                this.VariableValue = this.selectedVariable.CurrentValue;
                this.VariableName = this.selectedVariable.Name;
                this.VariableDescription = this.selectedVariable.Description;

                if (this.selectedVariable.Length == 0)
                {
                    this.VariableLength = "Unlimited";
                }
                else
                {
                    this.VariableLength = this.selectedVariable.Length.ToString() + (this.selectedVariable.IsFixedLength ? " (fixed length)" : string.Empty);
                }

                string serialization;

                switch (this.selectedVariable.IncrementType)
                {
                    case 1:
                        serialization = "Increment";
                        break;
                    case 2:
                        serialization = "Decrement";
                        break;
                    default:
                        serialization = "No serialization";
                        break;
                }

                if (this.selectedVariable.IncrementType != 0)
                {
                    serialization += " " + this.selectedVariable.IncrementStep.ToString() + " every " + this.selectedVariable.IncrementCount.ToString();
                }

                this.VariableSerialization = serialization;

                this.VariableIsUsed = this.selectedVariable.IsUsed ? "Yes" : "No";

                switch (this.selectedVariable.Format)
                {
                    case 0:
                        this.VariableFormat = "All";
                        break;
                    case 1:
                        this.VariableFormat = "Numeric";
                        break;
                    case 2:
                        this.VariableFormat = "Alphanumeric";
                        break;
                    case 3:
                        this.VariableFormat = "Letters";
                        break;
                    case 4:
                        this.VariableFormat = "Seven bit";
                        break;
                    case 5:
                        this.VariableFormat = "Hexadecimal";
                        break;
                    default:
                        this.VariableFormat = "Other";
                        break;
                }
            }
            else
            {
                this.VariableValue = string.Empty;
                this.VariableName = string.Empty;
                this.VariableDescription = string.Empty;
                this.VariableLength = string.Empty;
                this.VariableSerialization = string.Empty;
                this.VariableIsUsed = string.Empty;
                this.VariableFormat = string.Empty;
            }
        }

        #endregion
        public string VariableSerialization
        {
            get
            {
                return this.variableSerialization;
            }

            set
            {
                if (this.variableSerialization != value)
                {
                    this.variableSerialization = value;

                    this.NotifyPropertyChanged("VariableSerialization");
                }
            }
        }
        public string VariableIsUsed
        {
            get
            {
                return this.variableIsUsed;
            }

            set
            {
                if (this.variableIsUsed != value)
                {
                    this.variableIsUsed = value;

                    this.NotifyPropertyChanged("VariableIsUsed");
                }
            }
        }
        public string VariableLength
        {
            get
            {
                return this.variableLength;
            }

            set
            {
                if (this.variableLength != value)
                {
                    this.variableLength = value;

                    this.NotifyPropertyChanged("VariableLength");
                }
            }
        }
        public string VariableDescription
        {
            get
            {
                return this.variableDescription;
            }

            set
            {
                if (this.variableDescription != value)
                {
                    this.variableDescription = value;

                    this.NotifyPropertyChanged("VariableDescription");
                }
            }
        }
        public string VariableName
        {
            get
            {
                return this.variableName;
            }

            set
            {
                if (this.variableName != value)
                {
                    this.variableName = value;

                    this.NotifyPropertyChanged("VariableName");
                }
            }
        }
        public string VariableValue
        {
            get
            {
                return this.variableValue;
            }

            set
            {
                if (this.variableValue != value)
                {
                    this.variableValue = value;
                    this.NotifyPropertyChanged("VariableValue");
                }

                this.NotifyPropertyChanged("VariableValueDescription");
            }
        }
        public string VariableFormat
        {
            get
            {
                return this.variableFormat;
            }

            set
            {
                if (this.variableFormat != value)
                {
                    this.variableFormat = value;

                    this.NotifyPropertyChanged("VariableFormat");
                }
            }
        }
        public string LabelFileName
        {
            get
            {
                return this.labelFileName;
            }

            set
            {
                if (this.labelFileName != value)
                {
                    this.labelFileName = value;
                    this.NotifyPropertyChanged("LabelFileName");
                    this.NotifyPropertyChanged("LabelFileNameOnly");
                    this.NotifyPropertyChanged("LabelFileLocation");
                }
            }
        }

        private List<string> printBox = null;
        private BoxNumEntity printEntity = null;
        private string PrinterName = "";
        private Action action1;
        private Action<string> action2;
        private int boxNumLength;

        public PrintHelper(List<string> printBox, BoxNumEntity printEntity, string printerName,int boxNumLength, Action btnAction,Action<string> boxNumAction)
        {
            try
            {
                this.printBox = printBox;
                this.printEntity = printEntity;
                this.PrinterName = printerName;
                this.PrintRequests = new ObservableCollection<IPrintRequest>();
                this.action1 = btnAction;
                this.boxNumLength = boxNumLength;
                this.action2 = boxNumAction;
            }
            catch (Exception ex)
            {
                _log.Error(ex.ToString());
            }
        }

        public void PrintBox()
        {
            try
            {
                var path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "/template/cpbq.nlbl";
                this.LabelFileName = path;
                this.Label = this.PrintEngine.OpenLabel(this.LabelFileName);
                if (this.Label != null)
                {
                    this.Label.PrintSettings.PrinterName = this.PrinterName;
                    this.Label.PrintSettings.MonitorSpoolJobStatus = true;
                    ISessionPrintRequest sessionPrintRequest = this.Label.StartSessionPrint();
                    this.SessionPrintRequest = sessionPrintRequest;
                    this.SessionPrintRequest.SpoolJobStatusChanged += SessionPrintRequest_SpoolJobStatusChanged;
                    this.PrintRequests.Add(sessionPrintRequest);

                    foreach (var item in printBox)
                    {
                        var a1 = this.Label.Variables["a1"];
                        a1.SetValue(printEntity.FinishedProductName);
                        var a2 = this.Label.Variables["a2"];
                        a2.SetValue(item);
                        var a3 = this.Label.Variables["a3"];
                        a3.SetValue(printEntity.OrderId);
                        var a4 = this.Label.Variables["a4"];
                        a4.SetValue(printEntity.Batch);
                        var a5 = this.Label.Variables["a5"];
                        a5.SetValue(printEntity.OneBoxCount.ToString());
                        var a6 = this.Label.Variables["a6"];
                        a6.SetValue(printEntity.JuanNum);
                        var a7 = this.Label.Variables["a7"];
                        a7.SetValue(printEntity.MaoZhong);
                        var a8 = this.Label.Variables["a8"];
                        a8.SetValue(printEntity.Operator);
                        this.Label.SessionPrint(1, this.SessionPrintRequest);
                    }
                    this.Label.EndSessionPrint(this.SessionPrintRequest);
                    this.SessionPrintRequest = null;
                }
            }
            catch (Exception ex)
            {
                _log.Error(ex.ToString());
                MessageBox.Show("打印失败,请在检查打印机及其配置后重试!", "信息提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void SessionPrintRequest_SpoolJobStatusChanged(object sender, EventArgs e)
        {
            IPrintRequest printRequest = sender as IPrintRequest;
            if (printRequest.SpoolJobStatus == SpoolJobStatus.Error)
            {
                MessageBox.Show("打印失败!", "信息提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            else if (printRequest.SpoolJobStatus == SpoolJobStatus.Printed)
            {
                using (var Conn = MySqlHelper.getConnectionEx())
                {
                    MySqlTransaction trans = null;
                    try
                    {
                        Conn.Open();
                        trans = Conn.BeginTransaction();

                        #region 更新箱号
                        
                        var lastBoxNum = Convert.ToInt32(printBox[printBox.Count - 1].Substring(4));
                        string updatesql = string.Format("UPDATE Changeful set BoxNum = '{0}'", lastBoxNum);
                        Conn.Execute(updatesql, trans, null, null);

                        
                        #endregion

                        #region 保存箱号记录
                        string boxNumStr = "";
                        foreach (var item in printBox)
                        {
                            boxNumStr += item.ToString() + "-";
                        }
                        boxNumStr = boxNumStr.Remove(boxNumStr.Length - 1, 1);
                        string insertsql = string.Format("INSERT INTO Boxnum(Id,OrderId,LineType,FinishedProductName,Batch,Operator,CreateTime,JuanNum,MaoZhong,OneBoxCount,Store,AllCount,BoxNum)values ('{0}','{1}','{2}','{3}','{4}','{5}','{6}','{7}','{8}','{9}','{10}','{11}','{12}')", printEntity.Id, printEntity.OrderId, printEntity.LineType, printEntity.FinishedProductName, printEntity.Batch, printEntity.Operator, printEntity.CreateTime, printEntity.JuanNum, printEntity.MaoZhong, printEntity.OneBoxCount, printEntity.Store, printEntity.AllCount, boxNumStr);
                        int insertflag = Conn.Execute(insertsql, trans, null, null);
                        #endregion

                        var productList = productBLL.GetListByWhere(string.Format("ProductName = '{0}'", printEntity.FinishedProductName));
                        if (productList == null || productList.Count() == 0)
                        {
                            ProductEntity productEntity = new ProductEntity();
                            productEntity.Id = Guid.NewGuid().ToString();
                            productEntity.ProductCode = printEntity.FinishedProductName;
                            productEntity.ProductName = printEntity.FinishedProductName;
                            productEntity.CreateTime = DateTime.Now;
                            productEntity.UpdateTime = DateTime.Now;
                            productBLL.Insert(productEntity);
                        }

                        var stackInEntitys = stackInBLL.GetListByWhere(string.Format("ProductName like '%{0}%'and StackLocation like '%{1}%'", printEntity.FinishedProductName, printEntity.Store)).ToList();
                        if (stackInEntitys != null && stackInEntitys.Count > 0)
                        {
                            var temp = stackInEntitys[0];

                            string sql = string.Format("select * from StackIn where id = '{0}' for update;", temp.Id);
                            var readStackInEntity = Conn.QueryFirstOrDefault<StackInEntity>(sql, trans, null, null);
                            if (readStackInEntity != null)
                            {
                                readStackInEntity.ProductCount = printEntity.AllCount + readStackInEntity.ProductCount;
                                string sql1 = string.Format("UPDATE StackIn set ProductCount = '{1}',StackLocation = '{2}',IsStack = true where Id = '{0}'", readStackInEntity.Id, readStackInEntity.ProductCount, readStackInEntity.StackLocation);
                                int flag2 = Conn.Execute(sql1, trans, null, null);
                                if (flag2 == 1)
                                {
                                    StackLogEntity stackLogEntity = new StackLogEntity();
                                    stackLogEntity.Id = Guid.NewGuid().ToString();
                                    stackLogEntity.StackOrderId = readStackInEntity.Id;
                                    stackLogEntity.StackLocation = readStackInEntity.StackLocation;
                                    stackLogEntity.LogType = "1";
                                    stackLogEntity.Note = "累加入库；货品：" + temp.ProductName + "；在库位" + temp.StackLocation + "上累加的数量为：" + printEntity.AllCount;
                                    stackLogEntity.CreateTime = DateTime.Now;
                                    stackLogEntity.UpdateTime = DateTime.Now;
                                    stackLogBLL.Insert(stackLogEntity);
                                }
                                //MessageBox.Show("入库成功", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                                trans.Commit();
                            }
                            else
                                trans.Commit();
                        }
                        else
                        {
                            StackInEntity stackInEntity = new StackInEntity();
                            stackInEntity.Id = Guid.NewGuid().ToString();
                            stackInEntity.IsStack = true;
                            stackInEntity.StackLocation = printEntity.Store;
                            stackInEntity.ProductName = printEntity.FinishedProductName;
                            stackInEntity.ProductCode = printEntity.FinishedProductName;
                            stackInEntity.ProductCount = printEntity.AllCount;
                            stackInEntity.Type = "合格入库";
                            stackInEntity.CreateTime = DateTime.Now;
                            stackInEntity.UpdateTime = DateTime.Now;
                            var flag2 = stackInBLL.Insert(stackInEntity);
                            if (flag2)
                            {
                                StackLogEntity stackLogEntity = new StackLogEntity();
                                stackLogEntity.Id = Guid.NewGuid().ToString();
                                stackLogEntity.StackOrderId = stackInEntity.Id;
                                stackLogEntity.StackLocation = stackInEntity.StackLocation;
                                stackLogEntity.LogType = "0";
                                stackLogEntity.Note = "新增入库；货品：" + stackInEntity.ProductName + "在该库位" + stackInEntity.StackLocation + "新增数量为" + stackInEntity.ProductCount;
                                stackLogEntity.CreateTime = DateTime.Now;
                                stackLogEntity.UpdateTime = DateTime.Now;
                                stackLogBLL.Insert(stackLogEntity);
                            }
                            trans.Commit();
                        }
                        MessageBox.Show("已打印!", "信息提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                        //生成新箱号
                        var newBoxNum = lastBoxNum + 1;
                        var len1 = newBoxNum.ToString().Length;
                        string zero = "";
                        for (int j = len1; j < boxNumLength; j++)
                        {
                            zero += "0";
                        }
                        var NewBoxNum = zero.ToString() + newBoxNum.ToString();
                        action2(DateTime.Now.Year.ToString() + NewBoxNum);
                        action1();
                        printBox.Clear();
                    }
                    catch (Exception ex)
                    {
                        trans.Rollback(); //回滚
                        MessageBox.Show("入库失败!", "信息提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }
                    finally
                    {
                        printBox.Clear();
                        trans.Dispose(); //释放
                        Conn.Close();
                    }
                }
            }
        }
    }
}
